//
//  Barcode.swift
//  iPhone
//
//  Created by Toj on 6/9/22.
//

import UIKit

private let k_INPUT_MESSAGE = "inputMessage"
private let k_INPUT_CORRECTION_LEVEL = "inputCorrectionLevel"

/** 条码类型 */
public enum STBarCodeType: String {
    case qr     = "CIQRCodeGenerator"       // 二维码
    case bar    = "CICode128BarcodeGenerator" // 条形码
    case aztec  = "CIAztecCodeGenerator" // 特殊二维码(不建议)
    case pdf    = "CIPDF417BarcodeGenerator" // 拉伸条形码(不建议)
    
    var isQR: Bool {
        return self == .qr
    }
}

/** 容错率:
 *  二维码最多被遮挡多少面积依旧能被识别.
 *  所以我们可以自己制作带图标的二维码, 生成普通的二维码直接在除3个边角矩形框
 *  这三个小方块就是二维码位置信息, 用于定位二维码位置的 任意位置贴上想要的图标即可,
 *  只要图标面积不超过容错率上限都可以被识别.
 */
public enum STCorrectionLevel: String {
    /** 不需要容错 */
    case n  = ""
    /** 7% */
    case l  = "L"
    /** 15% */
    case m  = "M"
    /** 25% */
    case q  = "Q"
    /** 30% */
    case h  = "H"
}

open class STBarCode: NSObject {
    static let shared = STBarCode()
    // 容错率
    var level: STCorrectionLevel = .m
    
    private let queue = DispatchQueue.global(qos: .background)
    
    // 二维码
    public func qrCode(content: String, size: CGSize, completion: ((_ image: UIImage?)->Void)? = nil) {
        generator(content: content, size: size, type: .qr, completion: completion)
    }
    
    // 条形码
    public func barCode(content: String, size: CGSize, completion: ((_ image: UIImage?)->Void)? = nil) {
        generator(content: content, size: size, type: .bar, completion: completion)
    }
    
    public func generator(content: String, size: CGSize, type: STBarCodeType, completion: ((_ image: UIImage?)->Void)? = nil) {
        
        queue.async {
            guard let outputImage = self.filterOutputImage(name: type.rawValue, content: content) else {
                completion?(nil)
                return
            }
            
            // 去掉模糊, 生成指定大小条码图片
            let image = outputImage.removeEffect(size: size)
            DispatchQueue.main.async {
                completion?(image)
            }
        }
    }
    
    private func filterOutputImage(name: String, content: String) -> CIImage? {
        let contentData = content.to_utf8
        
        // 二维码滤镜
        let cfilter = CIFilter(name: name)
        /// 滤镜内容: (只能通过KVC)
        // 内容
        cfilter?.setValue(contentData, forKey: k_INPUT_MESSAGE)
        // 容错率, 对二维码有效
        if level != .n {
            cfilter?.setValue(level.rawValue, forKey: k_INPUT_CORRECTION_LEVEL)
        }
        
        // 恢复默认值: 将筛选器的所有输入值设置为默认值
        cfilter?.setDefaults()
        
        return cfilter?.outputImage
    }
}
